/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.rh.gui.jframe;

import com.rh.game.EquipmentChange;
import com.rh.game.Tile;
import com.rh.game.World;

import com.rh.gui.Gui;
import com.rh.gui.RenderEvent;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Toolkit;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import java.io.InputStream;
import java.io.IOException;

import java.util.ArrayList;
import java.util.List;

import javax.swing.JPanel;

/**
 *
 * @author Hayden
 */
public class TileGridJPanel extends JPanel implements KeyListener {
    private Image[] images = new Image[8];
    
    private static void debug(Object o)  {
        // System.out.println("TileGridJPanel: " + o);
    }
    
    private static final int TILE_SIZE = 40;
    
    private static final int ROWS = 5;
    private static final int COLS = 4;
    
    private Gui gui = null;
    private World world = null;

    private Toolkit toolkit = null;
    private MediaTracker tracker = null;
    
    public TileGridJPanel(Gui pGui, World pWorld)  {
        super();
        gui = pGui;
        world = pWorld;
        toolkit = Toolkit.getDefaultToolkit();
        tracker = new MediaTracker(this);
        initComponents();
        setupImages(pWorld.getTiles());
    }
    
    private void initComponents()  {
        this.setPreferredSize(new Dimension(TILE_SIZE * (2 * COLS + 1), TILE_SIZE * (2 * ROWS + 1)));
        this.addKeyListener(this);
    }
    
    public static void close(InputStream is)  {
        if (is == null)  return;
        try  {
            is.close();
        }
        catch (java.io.IOException ioe)  {
            ioe.printStackTrace();
        }
    }

    private Image load(String pFile)  {
        debug("loading image...");
        InputStream is = null;
        Image img = null;
        
        try  {
            debug(pFile);
            is = this.getClass().getResourceAsStream(pFile);
            debug(is);
            int available = is.available();
            byte[] b = new byte[available];
            
            while (available > 0)  {
                int count = 0;
                while (count < available)  {
                    count += is.read(b, count, available - count);
                }

                available = is.available();
                if (available > 0)  {
                    byte[] temp = new byte[b.length + available];
                    System.arraycopy(b, b.length, temp, 0, b.length);
                    b = temp;
                }
            }
            
           img = toolkit.createImage(b);
           tracker.addImage(img, 0);
           tracker.waitForAll();            
        }
        catch (InterruptedException ie)  {
            ie.printStackTrace();
        }
        catch (IOException ioe)  {
            ioe.printStackTrace();
        }
        finally  {
            close(is);
        }
        
        return img;
    }
    
    private void setupImages(List<Tile> tileImages)  {
        int x = 0;
        for (Tile t : tileImages)  {
            System.out.println(t);
            x = Math.max(x, t.getID());
        }
        images = new Image[x+1];
        for (int i1=0; i1<tileImages.size(); i1++)  {
            images[tileImages.get(i1).getID()] = load(tileImages.get(i1).getResource());
        }
    }
    
    public void keyTyped(KeyEvent e) {
        debug("keyTyped := " + e);
    }

    public void keyPressed(KeyEvent e) {
        debug("keyPressed := " + e);
    }

    public void keyReleased(KeyEvent e) {
        debug(e);
        List<RenderEvent> re = new ArrayList<RenderEvent>();
        // Character
        if ((e.getKeyChar() == 'c') || (e.getKeyChar() == 'C'))  {
            EquipmentChange ec = gui.character(world.getPlayer());
            re.addAll(world.equipment(world.getPlayer(), ec));
        }
        
        // Talk
        if ((e.getKeyChar() == 't') || (e.getKeyChar() == 'T'))  {
            re.addAll(world.processInput("CHAT"));
        }
        
        // Move
        if ((e.getKeyChar() == 'a') || (e.getKeyChar() == 'A') || (e.getKeyCode() == 37))  {
            re.addAll(world.processInput("MOVE LEFT"));
        }
        if ((e.getKeyChar() == 'd') || (e.getKeyChar() == 'D') || (e.getKeyCode() == 39))  {
            re.addAll(world.processInput("MOVE RIGHT"));
        }
        if ((e.getKeyChar() == 's') || (e.getKeyChar() == 'S') || (e.getKeyCode() == 40))  {
            re.addAll(world.processInput("MOVE DOWN"));
        }
        if ((e.getKeyChar() == 'w') || (e.getKeyChar() == 'W') || (e.getKeyCode() == 38))  {
            re.addAll(world.processInput("MOVE UP"));
        }
        
        debug(world.getPlayer().getLocation().toString());
        gui.render(re, world);
    }
    
    @Override
    public void paint(Graphics gph)  {
        Graphics2D g = (Graphics2D) gph;
        byte[][] data = world.getGrid();
        debug("Grid length: " + data.length);
        
        int px = world.getPlayer().getLocation().getX();
        int py = world.getPlayer().getLocation().getY();

        int drawRow = 0;
        int drawCol = 0;
        
        for (int y=py-ROWS; y<=py+ROWS; y++)  {
            drawCol = 0;
            for (int x=px-COLS; x<=px+COLS; x++)  {
                // debug("paint x,y " + x + ", " + y + " ==> " + drawCol + ", " + drawRow);
                
                boolean black = false;
                Image i = null;
                
                if (y<0)  black = true;
                else if (y>=data.length)  black = true;
                else if (x<0)  black = true;
                else if (x>=data[y].length)  black = true;
                else   {
                    byte b = data[y][x];
                    if ((b >=0) && (b < images.length))  i = images[b];                    
                }
                
                if ((black) || (i == null))  {
                    g.setColor(Color.DARK_GRAY);
                    g.fillRect(drawCol*TILE_SIZE, drawRow*TILE_SIZE, TILE_SIZE, TILE_SIZE);
                    g.setColor(g.getColor().darker());
                    g.drawRect(drawCol*TILE_SIZE, drawRow*TILE_SIZE, TILE_SIZE, TILE_SIZE);                                        
                }
                else  {
                    g.drawImage(i, drawCol*TILE_SIZE, drawRow*TILE_SIZE, null);                    
                }
                
                drawCol++;
            }
            drawRow++;
        }
    }
}
